
import sys
import json
import numpy as np
import matplotlib.pyplot as plt

from os import listdir
from os.path import isfile, join
from skimage.data import imread
from skimage.io import imsave
from skimage.filters import gaussian


########################################################################################################################

def blur_image(img, ann):
	img_blury_20 = gaussian(img, sigma=18, multichannel=True)
	img_blury_15 = gaussian(img, sigma=13, multichannel=True)
	img_blury_10 = gaussian(img, sigma=8, multichannel=True)
	img_blury_5 = gaussian(img, sigma=4, multichannel=True)
	img = img / 255.0

	img_bluriest = img_blury_20
	blured_imgs = [img_blury_15, img_blury_10, img_blury_5, img]
	expansion_factors = [2.0, 1.8, 1.6, 1.4]

	img_width = ann["img_width"]
	img_height = ann["img_height"]

	for i, blured_img in enumerate(blured_imgs):
		for face in ann["face"]:
			f_position = face["position"]
			x_c = (f_position["center"]["x"] / 100.0) * img_width
			y_c = (f_position["center"]["y"] / 100.0) * img_height
			w = (f_position["width"] / 100.0) * img_width
			h = (f_position["height"] / 100.0) * img_height

			# blur specific
			w_i = w * expansion_factors[i]
			h_i = h * expansion_factors[i]

			x_start, x_end = int(x_c - w_i / 2), int(x_c + w_i / 2)
			y_start, y_end = int(y_c - h_i / 2), int(y_c + h_i / 2)

			for x in range(x_start, x_end):
				for y in range(y_start, y_end):
					if (y >= 0 and y < img.shape[0]) and (x >= 0 and x < img.shape[1]):
						img_bluriest[y, x] = blured_img[y, x]


	img_bluriest[img_bluriest < -1.0] = -1.0
	img_bluriest[img_bluriest > 1.0] = 1.0

	return img_bluriest

########################################################################################################################

def display_pre_post_blur(img, blurred_img):
	fig, ax = plt.subplots(ncols=2, subplot_kw={'adjustable': 'box-forced'})

	ax[0].imshow(img, cmap=plt.cm.gray)
	ax[0].axis('off')

	ax[1].imshow(blurred_img, cmap=plt.cm.gray)
	ax[1].axis('off')

	plt.show()

########################################################################################################################

def test():
	root = "../data/Boston"
	img_name = "805428172838412"

	img_path = "%s/photos/%s.jpg" % (root, img_name)
	ann_path = "%s/annotations/%s.json" % (root, img_name)
	out_path = "%s/photos_blurred/%s.jpg" % (root, img_name)

	# load image and annotations
	img = imread(img_path)
	ann = json.load(open(ann_path))

	# blur image
	blurred_img = blur_image(img, ann)

	# show images
	display_pre_post_blur(img, blurred_img)

	#imsave(out_path, blurred_img)

########################################################################################################################
#
# MAIN
#
########################################################################################################################

def main():
	loc = sys.argv[1]
	root = "../data/%s" % loc
	photos_root = "%s/photos/" % root
	ferr = open(root + "/photos_blurred/_errors.txt", "w")

	for i, fname in enumerate(listdir(photos_root)):
		try:
			# check that the file matches the expected format
			if fname.endswith(".jpg") == False:
				continue

			# setup image name and paths
			img_name = fname.split(".")[0]

			img_path = "%s/photos/%s.jpg" % (root, img_name)
			ann_path = "%s/annotations/%s.json" % (root, img_name)
			out_path = "%s/photos_blurred/%s.jpg" % (root, img_name)

			# check if the image and annotation files exist
			if (isfile(img_path) and isfile(ann_path)) == False:
				continue

			# load image and annotations
			img = imread(img_path)
			ann = json.load(open(ann_path))

			# blur image
			blurred_img = blur_image(img, ann)

			# save blurred image
			imsave(out_path, blurred_img)

			print "%d %s %s" % (i, loc, img_name)

		except Exception as e:
			print e
			print "%d %s %s ... FAILED" % (i, loc, img_name)
			ferr.write("%d %s\n" % (i, fname))
			ferr.flush()

########################################################################################################################

if __name__ == "__main__":
    main()
    #test()

# END
